Skip to content

Editorial review: Document WebXR visibilitymaskchange event#43975

Open
chrisdavidmills wants to merge 13 commits into
mdn:mainfrom
chrisdavidmills:xrsession-visibilitymaskchange-event
Open

Editorial review: Document WebXR visibilitymaskchange event#43975
chrisdavidmills wants to merge 13 commits into
mdn:mainfrom
chrisdavidmills:xrsession-visibilitymaskchange-event

Conversation

@chrisdavidmills
Copy link
Copy Markdown
Contributor

Description

Chrome 144 adds support for the visibilitymaskchange event/XRVisibilityMaskChange event object; see https://chromestatus.com/feature/5073760055066624.

This PR adds documentation for:

  • The XRVisibilityMaskChange event object and all its members.
  • The visibilitymaskchange event
  • The XRView.index property.

Motivation

Additional details

Related issues and pull requests

@chrisdavidmills chrisdavidmills requested a review from a team as a code owner April 30, 2026 13:54
@chrisdavidmills chrisdavidmills requested review from hamishwillee and removed request for a team April 30, 2026 13:54
@github-actions github-actions Bot added the Content:WebAPI Web API docs label Apr 30, 2026
@chrisdavidmills chrisdavidmills changed the title Document visibilitymaskchange event Technical review: Document WebXR visibilitymaskchange event Apr 30, 2026
@github-actions github-actions Bot added the size/m [PR only] 51-500 LoC changed label Apr 30, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 30, 2026

Preview URLs (12 pages)

Flaws (5)

Note! 8 documents with no flaws that don't need to be listed. 🎉

Found an unexpected or unresolvable flaw? Please report it here.

URL: /en-US/docs/Web/API/WebXR_Device_API
Title: WebXR Device API
Flaw count: 1

  • macros:
    • Macro domxref produces link /en-US/docs/Web/API/XRPermissionStatus which doesn't resolve

URL: /en-US/docs/Web/API/XRVisibilityMaskChangeEvent/indices
Title: XRVisibilityMaskChangeEvent: indices property
Flaw count: 1

  • macros:
    • Macro domxref produces link /en-US/docs/Web/API/Uint32Array which is a redirect

URL: /en-US/docs/Web/API/XRVisibilityMaskChangeEvent/vertices
Title: XRVisibilityMaskChangeEvent: vertices property
Flaw count: 1

  • macros:
    • Macro domxref produces link /en-US/docs/Web/API/Float32Array which is a redirect

URL: /en-US/docs/Web/API/XRVisibilityMaskChangeEvent/XRVisibilityMaskChangeEvent
Title: XRVisibilityMaskChangeEvent: XRVisibilityMaskChangeEvent() constructor
Flaw count: 2

  • macros:
    • Macro domxref produces link /en-US/docs/Web/API/Uint32Array which is a redirect
    • Macro domxref produces link /en-US/docs/Web/API/Float32Array which is a redirect
External URLs (2)

URL: /en-US/docs/Web/API/XRSession/visibilitymaskchange_event
Title: XRSession: visibilitymaskchange event


URL: /en-US/docs/Web/API/XRVisibilityMaskChangeEvent
Title: XRVisibilityMaskChangeEvent

(comment last updated: 2026-05-15 07:34:18)

Comment thread files/en-us/web/api/xrvisibilitymaskchangeevent/session/index.md Outdated

{{APIRef("WebXR Device API")}}{{SecureContext_Header}}

The read-only **`vertices`** property of the {{domxref("XRVisibilityMaskChangeEvent")}} interface is an array of coordinates representing the vertices required to draw the entire scene displayed in the {{domxref("XRView")}}. If this array is empty, the whole region of the `XRView` will be drawn.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also reference here that it's intended to be referenced into by the indices property.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, makes sense. I've added the following in a new paragraph:

The {{domxref("XRVisibilityMaskChangeEvent.indices", "indices")}} array specifies the indices of the vertices array that should be drawn to display the currently visible part of the scene displayed in the XRView.

Copy link
Copy Markdown
Collaborator

@hamishwillee hamishwillee May 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More detail required than that to allow readers to understand what is going on

If these are floats, then they are numbers, not "points" so my guess in https://github.com/mdn/content/pull/43975/changes#r3215903956 is completely wrong. But the comment is valid - a reader should be able to work out how this works.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I've looked up some more information, adjusted the indices and vertices descriptions, and added a paragraph on how this actually works to the vertices page. I'm not 100% sure if I'm right, so it'd be good for @alcooper91 to check this over.

Copy link
Copy Markdown

@alcooper91 alcooper91 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@chrisdavidmills chrisdavidmills changed the title Technical review: Document WebXR visibilitymaskchange event Editorial review: Document WebXR visibilitymaskchange event May 1, 2026
Comment thread files/en-us/web/api/xrview/index/index.md
Comment thread files/en-us/web/api/xrview/index/index.md Outdated
Comment thread files/en-us/web/api/xrvisibilitymaskchangeevent/eye/index.md Outdated
Comment thread files/en-us/web/api/xrvisibilitymaskchangeevent/eye/index.md Outdated
Comment thread files/en-us/web/api/xrvisibilitymaskchangeevent/eye/index.md
Comment thread files/en-us/web/api/xrvisibilitymaskchangeevent/index/index.md Outdated
Comment thread files/en-us/web/api/xrvisibilitymaskchangeevent/indices/index.md Outdated
Comment thread files/en-us/web/api/xrvisibilitymaskchangeevent/indices/index.md Outdated
Comment thread files/en-us/web/api/xrvisibilitymaskchangeevent/session/index.md Outdated
Comment thread files/en-us/web/api/xrvisibilitymaskchangeevent/session/index.md
Comment thread files/en-us/web/api/xrvisibilitymaskchangeevent/session/index.md

{{APIRef("WebXR Device API")}}{{SecureContext_Header}}

The **`XRVisibilityMaskChangeEvent`** of the [WebXR Device API](/en-US/docs/Web/API/WebXR_Device_API) describes the portion of an {{domxref("XRView")}} visible to the user (that is, the portion not hidden by the mask) after the view has changed. This enables performance improvements by allowing the browser to draw only the visible part of the updated view.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This enables performance improvements by allowing the browser to draw only the visible part of the updated view.

Er, users get events - browsers generate them. So I can see that a browser can enable performance improvements, but it isn't clear what the user is supposed to do with this event and why it is relevant.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More text added to explain relevance


{{APIRef("WebXR Device API")}}{{SeeCompatTable}}{{SecureContext_Header}}

The **`visibilitymaskchange`** event is sent to an {{domxref("XRSession")}} when the portion of an {{domxref("XRView")}} visible to the user changes — that is, the portion not hidden by the mask. This enables performance improvements by allowing the browser to draw only the visible part of the updated view. The required information to draw the update is contained in the {{domxref("XRVisibilityMaskChangeEvent")}} event object.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See https://github.com/mdn/content/pull/43975/changes#r3215941539 - it isn't clear to me how this works, since events are handled by user code, but it talks about browser behaviour.

The required information to draw the update is contained in the {{domxref("XRVisibilityMaskChangeEvent")}} event object.

As I understand it the event is-a XRVisibilityMaskChangeEvent - this is an odd way to say that. Am I missing something?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tried shifting the explanation around a bit.

Comment thread files/en-us/web/api/xrsession/visibilitymaskchange_event/index.md
Comment thread files/en-us/web/api/xrsession/visibilitymaskchange_event/index.md
## Examples

### Basic usage
This example indicates how you might check a custom `userRequestsSessionEnd` value when the `visibilitymaskchange` event fires to see whether the user has manually selected an option to end the XR session. If so, you can access the `XRSession` via the `session` property and end the session using {{domxref("XRSession.end()")}}.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[mdn-linter] reported by reviewdog 🐶

Suggested change
This example indicates how you might check a custom `userRequestsSessionEnd` value when the `visibilitymaskchange` event fires to see whether the user has manually selected an option to end the XR session. If so, you can access the `XRSession` via the `session` property and end the session using {{domxref("XRSession.end()")}}.

chrisdavidmills and others added 12 commits May 15, 2026 09:56
Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@hamishwillee hamishwillee force-pushed the xrsession-visibilitymaskchange-event branch from 46ee5b6 to efa2466 Compare May 14, 2026 23:56
Comment thread files/en-us/web/api/xrsession/visibilitymaskchange_event/index.md Outdated

The {{domxref("XRVisibilityMaskChangeEvent.indices", "indices")}} array specifies the array positions of the vertices inside the `vertices` array that define the currently visible part of the scene displayed in the `XRView`.

The coordinate values available in the `vertices` array are x and y value pairs representing points on a flat mask in clip space. They define the boundary of the visibility mask — the region of the display that is actually visible to the user. Anything outside the mask is not visible to the user, and does not need to be drawn. It can be skipped to improve performance.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chrisdavidmills This is getting there, but I am still unsure.

What this says is that "vertices is an array of coordinate values representing a visibility mask" and the "indices array specifies the array positions of the vertices "

  1. From "vertices is an array of coordinate values representing a visibility mask" the implication is that the array defines the mask, so there doesn't seem to be any reason to need the indices array?
  2. My "guess" is that vertices contains a whole lot of points in an array and but not all of them are used for the mask - you iterate through indicies to find which points are relevant and then use them to build a mask. But
    • That isn't what it says.
    • If it is true I'd like to know why you don't just have verticies array that only contains the verticies that are needed.
    • I'd like to know how the mask is constructed from the verticies. Are they just points joined in order, with the mask being the inner polygon? That then being the "mask in clip space"
  3. The values are "x and y value pairs representing points". However a Float32Array is a flat array - i.e. it is a list of floats, not "inherently" a list of float pairs. So are we saying that each point is two elements in this array, x, followed by y.

An example in this page would not hurt.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah looking at your example in the interface page, I think they are encoded as x,y in order. Gemini seems to think that the points are interpretted as groups of triangles, which would imply that you must have a certain number of points to always divide cleanly by three.
If that's true, all needs to be captured.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so there doesn't seem to be any reason to need the indices array?

I don't know why this approach is used. I wondered about this as well. Maybe @alcooper91 can provide an answer here.

So are we saying that each point is two elements in this array, x, followed by y.

Yes, I believe so. And the z-axis value in each case is a constant value.

Copy link
Copy Markdown

@alcooper91 alcooper91 May 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes the Z is implied to be a constant value. You do need the indices array. It’s a common graphics tactic for encoding a mesh. Say the region is square.
vertices may be (groupings solely for the purpose of legibility in this discussion):
(0,0),(0,1),(1,1),(1,0)
With indices being: 0,1,2, 0,3,2

obviously for the simple square all the points could just define a polygon; but it’s meant to allow you to just pass the values to a graphics library. The indices should be a multiple of 3 representing the triangles used to build the mesh.

Comment on lines +29 to +30
- `indices`
- : A {{domxref("Uint32Array")}} of values specifying the array positions of the vertices in the [`vertices`](#vertices) array that define the currently visible part of the scene displayed in the `XRView`. If this array is empty, the whole region of the `XRView` will be drawn.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and vertices may be sufficient here, but I won't know until https://github.com/mdn/content/pull/43975/changes#r3245058413 is clarified

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. All three are needed. You need to know the view the mesh is applied to and then the vertices and indices define the triangles that make up the mesh. It’s a common graphics idiom.

Comment on lines +49 to +59
function onVisibilityMaskChange(event) {
const geometry = new BufferGeometry();
geometry.setIndex(new BufferAttribute(event.indices, 1));
const vertices = new Float32Array((event.vertices.length / 2) * 3);
let x = 0,
y = 0;
while (x < event.vertices.length) {
vertices[y++] = event.vertices[x++];
vertices[y++] = event.vertices[x++];
vertices[y++] = -1;
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could probably use some words. IN particular this looks like it is creating a three dimensional structure from the 2D point information in event.vertices - but I am not sure why?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per my other comment you need to iterate through the indices array. Not just increment your own indices.

@toji can help me out here, there MAY be a WebGL or other structure you can basically just pass them into

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is using Three.js, which (as far as I can tell) requires the 'position' attribute of a BufferGeometry to be a packed array of 3D points. So this type of conversion would be necessary.

With raw WebGL there's no specific requirement for the number of elements in an attribute, as the developer interprets it in the shaders. So there are scenarios where you could pass the event.vertices array in directly, just not with Three.js

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, just realized I probably read Alex's question wrong.

geometry.setIndex(new BufferAttribute(event.indices, 1)); as shown here is fine, because the indices are a Uint32Array and thus are already in the right format.

Copy link
Copy Markdown
Collaborator

@hamishwillee hamishwillee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting there. Probably needs a minor tweak after response to https://github.com/mdn/content/pull/43975/changes#r3245058413

Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Content:WebAPI Web API docs size/m [PR only] 51-500 LoC changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants